/**
 * Copyright (c) 2010-2011 Pierre Labatut
 *
 * This file is part of Space-Chronicles project.
 *
 * Space-Chronicles is free software: you can redistribute it and/or modify it
 * under the terms of its license which may be found in the accompanying
 * LICENSE file or <http://code.google.com/p/space-chronicles/>.
 */
package space.game.world;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.media.opengl.GL3bc;
import jinngine.geometry.Geometry;
import jinngine.math.Matrix4;
import jinngine.physics.Body;
import jinngine.physics.Scene;
import space.debug.GlobalParameters;
import space.game.WldMaterial;
import space.gl.RenderContext;
import space.gl.RenderContext.Pass;
import space.model.Actor;
import space.model.DrawGeometry;
import space.model.Drawable;
import space.model.MdlEmpty;
import space.model.MdlMeshArray;
import space.model.MdlObject;

/**
 *
 * @author Pierre
 */
public class WldInert implements Actor {

    public Body getBody() {
        return body;
    }
    protected final Matrix4 objectToBody;
    final Body body;
    Drawable rep;
    WldMaterial mat;
    final List<Drawable> engineGlow = new ArrayList<Drawable>();
    final List<Drawable> childs = new ArrayList<Drawable>();
    final List<Drawable> debug = new ArrayList<Drawable>();

    public WldInert(MdlObject obj, Map<String, Drawable> lib, Map<String, WldMaterial> materialLib, String identifier) {
        body = new Body(identifier);
        obj.addGeometry(body);

        for (MdlObject c : obj.getChilds()) {
            childs.add(new WldChild(c.getMatrix(), c, lib));
        }
        for (MdlObject c : obj.getEngineGlow()) {
            engineGlow.add(new WldChild(c.getMatrix(), c, lib));
        }
        for (MdlEmpty e : obj.empties()) {
            if (e.groupName.isEmpty() == false) {
                childs.add(new WldChild(e.matrix, (MdlObject) lib.get(e.groupName), lib));
            }
        }
        body.update();
        objectToBody = body.getTransform().inverse();
        /**
         * Build representations for collisions
         */
        final Iterator<Geometry> itr = body.getGeometries();
        while (itr.hasNext()) {
            debug.add(DrawGeometry.buildDrawable(itr.next()));
        }
        mat = obj.material(materialLib);
        rep = obj.representation();
    }

    public void spawn(final Scene scene) {
        scene.addBody(body);
    }

    public Drawable optimize(GL3bc gl) {
        rep = rep.optimize(gl);

        final ArrayList<Drawable> ochild = new ArrayList<Drawable>();
        for (Drawable drawable : childs) {
            ochild.add(drawable.optimize(gl));
        }
        childs.clear();
        childs.addAll(ochild);


        final ArrayList<Drawable> oglow = new ArrayList<Drawable>();
        for (Drawable drawable : engineGlow) {
            oglow.add(drawable.optimize(gl));
        }
        engineGlow.clear();
        engineGlow.addAll(oglow);

        return this;
    }

    public void draw(final RenderContext rc) {
        rc.compose(body.getTransform());//Body to world
        rc.compose(objectToBody);

        if (rc.pass() == Pass.ADDITIVE) {
            for (final Drawable md : engineGlow) {
                md.draw(rc.create());
            }

        } else {
            if (mat != null) {
                mat.draw(rc.gl());
            }
            rep.draw(rc.create());

            for (final Drawable md : childs) {
                md.draw(rc.create());
            }

            if (GlobalParameters.showDebug && rc.pass() == Pass.SHADE) {
                for (final Drawable md : debug) {
                    md.draw(rc.create());
                }
            }
        }


    }

    public void dispose(GL3bc gl) {
    }

    public void update(WldScene scene, double dt) {
    }

    public void setPosition(double x, double y, double z) {
        body.setPosition(x, y, z);
    }

    public MdlMeshArray leak() {
        //TODO: What is this leak?
        return (MdlMeshArray) rep;
    }
}
